Values Passing Conventions

The first nregs arguments are passed in registers, where nregs is an implementation dependent constant. Any additional arguments are the block of storage between CONT and CS on the control stack. The first nregs locations in this block of storage are unused so that register more-args can be stored on the stack without having to BLT the stack values up.

Returning unknown values are passed in a similar way, but the stack values block is between OLD-CONT and CS. There isn't any underneath the values: on return OLD-CONT is always what CS was when the function was called. The function returned to must copy the values into the desired location in its frame and deallocate excess stuff on the top of the stack.

More args are represented by a pointer to the block of values and a count. The function that originally created the more arg must allocate and deallocate this stuff somehow. In the case of a local call to a more arg entry, we can just allocate it as a TN. The external entry point for a more arg entry is more magical.

The caller allocates the environment for the called function, stores the arguments into it, and jumps to the function. The caller makes the called environment current, passing in the return OLD-CONT and PC as explicit arguments.

When returning values, the returner directly stores the return values into the frame being returned to. This works even though the caller doesn't know what function it is returning to, since the same return locations are allocated in all frames.

In a tail-recursive call, we can destructively modify the current frame and jump right to the callee, rather than allocating a new frame. We can do this because TNBind globally allocates frame locations; all frames are the same size and have the same TNs in the same place.